home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / crossedit / Cnv / CnvPath.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  13KB  |  479 lines

  1. /*
  2.  * CnvPath - file selector
  3.  * Copyright (C) 1993 Petri Heinila
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  * Author can be connected by email from hevi@lut.fi
  20.  */
  21.  
  22. #include <Cnv.h>
  23. #include <debug.h>
  24. #include <assert.h>
  25.  
  26. /**********************************************************************
  27.  * declarations
  28.  **********************************************************************/
  29.  
  30. static void CnvPathListInit(CnvPath p);
  31. static void CnvPathListGet(CnvPath p,String path);
  32. static void CnvPathEnter(CnvPath self);
  33. static Boolean hasActions = False;
  34. static CnvPath tmpCnvPath = NULL;
  35.  
  36. /**********************************************************************
  37.  * actions
  38.  **********************************************************************/
  39.  
  40. static void CnvPathReturn(Widget w,XEvent *e,String *argv, Cardinal *argc);
  41.  
  42. static XtActionsRec actions[] = {
  43.   {"CnvPathReturn", CnvPathReturn}  /* when user accept */
  44. };
  45.  
  46. static void CnvPathReturn(Widget w,XEvent *e,String *argv, Cardinal *argc)
  47. {
  48.     CnvPath self = (CnvPath)tmpCnvPath;
  49.     assert(self);
  50.     CnvPathEnter(self);
  51. }
  52.  
  53. /**********************************************************************
  54.  * widgets
  55.  **********************************************************************/
  56.  
  57. static void CnvPathCancelCb(Widget w,XtPointer client,XtPointer call)
  58. {
  59.   CnvPath p = (CnvPath)client;
  60.   p->hold = CnvPathCancel;
  61. }
  62.  
  63. static void CnvPathEnterCb(Widget w,XtPointer client,XtPointer call)
  64. {
  65.   CnvPath self = (CnvPath)client;
  66.   CnvPathEnter(self);
  67. }
  68.  
  69. static void CnvPathSelectFileCb(Widget w,XtPointer client,XtPointer call)
  70. {
  71.   CnvPath p = (CnvPath)client;
  72.   XawListReturnStruct *ret = (XawListReturnStruct*)call;
  73.  
  74.   XtVaSetValues(p->text,
  75.         XtNstring,ret->string,
  76.         NULL);
  77. }
  78.  
  79. static void CnvPathSelectDirCb(Widget w,XtPointer client,XtPointer call)
  80. {
  81.   CnvPath p = (CnvPath)client;
  82.   XawListReturnStruct *ret = (XawListReturnStruct*)call;
  83.   char path[PATH_MAX+1];
  84.  
  85.   if(strcmp(ret->string,"..") == 0) {
  86.     char *str;
  87.     pathcpy(path,p->current);
  88.     str = path + strlen(path);
  89.     while(*str != '/' && str > path) str--;
  90.     *str = 0;
  91.   } else   if(strcmp(ret->string,".") == 0) {
  92.     sprintf(path,"%s",p->current);        
  93.   } else {
  94.     sprintf(path,"%s/%s",p->current,ret->string);    
  95.   }
  96.   p->hold = CnvPathHold;
  97.   CnvPathListGet(p,path);
  98. }
  99.  
  100. /**********************************************************************
  101.  * Layout
  102.  **********************************************************************/
  103.  
  104. static void Layout(CnvPath self,String name)
  105. {
  106.   Widget cont,cancel,fileView,dirView,ok;
  107.  
  108.   self->shell = XtVaCreatePopupShell
  109.     (name,transientShellWidgetClass,cnv->shell,NULL);
  110.   cont = XtVaCreateManagedWidget
  111.     ("cont",formWidgetClass,self->shell,
  112.      NULL);
  113.   self->cwd = XtVaCreateManagedWidget
  114.     ("cwd",labelWidgetClass,cont,
  115.      /*
  116.      XtNfromHoriz,NULL,
  117.      XtNfromVert,NULL,
  118.      */
  119.      NULL);
  120.   self->text = XtVaCreateManagedWidget
  121.     ("text",asciiTextWidgetClass,cont,
  122.      XtNtype,XawAsciiString,
  123.      XtNeditType,XawtextEdit,
  124.      XtNfromHoriz,self->cwd,
  125.      XtNfromVert,NULL,
  126.      XtNaccelerators,XtParseAcceleratorTable
  127.      ("#override <Key>Return: CnvPathReturn() \n"),
  128.      XtNtranslations,XtParseTranslationTable
  129.      ("#override <Key>Tab: CnvNop()\n"
  130.       "<Key>Return: CnvPathReturn() \n"),
  131.      NULL);
  132.   fileView = XtVaCreateManagedWidget
  133.     ("fileView",viewportWidgetClass,cont,
  134.      XtNfromHoriz,NULL,
  135.      XtNfromVert,self->cwd,
  136.      NULL);
  137.   self->fileList = XtVaCreateManagedWidget
  138.     ("fileList",listWidgetClass,fileView,
  139.      XtNtranslations,XtParseTranslationTable
  140.      ("#override <Btn1Up>(2): Set() Notify() CnvPathReturn()\n" 
  141.       "<Btn1Down>: Set() Notify() \n"),
  142.      NULL);
  143.   XtAddCallback(self->fileList,XtNcallback,CnvPathSelectFileCb,
  144.         (XtPointer)self);
  145.   dirView = XtVaCreateManagedWidget
  146.     ("dirView",viewportWidgetClass,cont,
  147.      XtNfromHoriz,fileView,
  148.      XtNfromVert,self->cwd,
  149.      NULL);
  150.   self->dirList = XtVaCreateManagedWidget
  151.     ("dirList",listWidgetClass,dirView,
  152.      NULL);
  153.   XtAddCallback(self->dirList,XtNcallback,CnvPathSelectDirCb,(XtPointer)self);
  154.   ok = XtVaCreateManagedWidget
  155.     ("ok",commandWidgetClass,cont,
  156.      XtNfromHoriz,NULL,
  157.      XtNfromVert,fileView,
  158.      NULL);
  159.   XtAddCallback(ok,XtNcallback,CnvPathEnterCb,(XtPointer)self);
  160.   cancel = XtVaCreateManagedWidget
  161.     ("cancel",commandWidgetClass,cont,
  162.      XtNfromHoriz,ok,
  163.      XtNfromVert,fileView,
  164.      NULL);
  165.   XtAddCallback(cancel,XtNcallback,CnvPathCancelCb,(XtPointer)self);
  166.   XtInstallAllAccelerators(cont,cont);
  167. }
  168.  
  169. /**********************************************************************
  170.  * 
  171.  **********************************************************************/
  172.  
  173. /*
  174.  * function: select a filepath
  175.  */
  176. static void CnvPathEnter(CnvPath self)
  177. {
  178.     String str;
  179.     
  180.     self->hold = CnvPathOk;
  181.     XtVaGetValues(self->text,
  182.           XtNstring,&str,
  183.           NULL);
  184.     namecpy(self->filename,str);
  185. }
  186.  
  187. /*
  188.  * implicit: App app
  189.  */
  190. static void CnvPathListInit(CnvPath p)
  191. {
  192.   int i;
  193.  
  194.   for(i=0; i < EntryMax; i++) {
  195.     /* debug1("i:%i\n",i); */
  196.     p->fileTable[i] = NULL;
  197.   }
  198.   for(i=0; i < EntryMax; i++) {
  199.     /* debug1("i2:%i\n",i); */
  200.     p->dirTable[i] = NULL;
  201.   }
  202.   p->fileNro = 0;
  203.   p->dirNro = 0;
  204.   *(p->filename) = 0;
  205. }
  206.  
  207. /*
  208.  * compare funtion for sorting in CnvPathListGet()
  209.  */
  210. static int StrCmp (const void **s1, const void **s2)
  211. {
  212.     return strcmp (*s1, *s2);
  213. }
  214.  
  215. /*
  216.  * read files and directories from given absolute dir
  217.  * update them into Path structure. directoty is a crossfire
  218.  * part of file name ie. LibDir/MapDir<dirname>, althought
  219.  * it is absolute name in it part, ie it have to begin with '/'.
  220.  */
  221. static void CnvPathListGet(CnvPath self,String directory)
  222. {
  223.   DIR *dir;
  224. #ifdef NeXT
  225.   struct direct *dirent;
  226. #else
  227.   struct dirent *dirent;
  228. #endif
  229.   struct stat statbuf;
  230.   Cardinal i,fileOld,dirOld;
  231.   char path[PATH_MAX+1],full[PATH_MAX+1];
  232.  
  233.   /*** form full dir name ***/
  234.   sprintf(full,"%s%s",self->root,directory);
  235.   debug1("CnvPathListGet(), rescan %s\n",full);
  236.  
  237.   /*** open it ***/
  238.   if(CnvPathNoAccess(self->shell, full)) return;
  239.   if((dir = opendir(full)) == NULL) CnvDie(self->shell,full);
  240.   XtVaSetValues(self->cwd,
  241.           XtNlabel,directory,
  242.           NULL);
  243.   pathcpy(self->current,directory);
  244.  
  245.   /*** read dir & files ***/
  246.   fileOld = self->fileNro;
  247.   dirOld = self->dirNro;
  248.   self->fileNro = 0;
  249.   self->dirNro = 0;
  250.   while((dirent = readdir(dir)) != NULL) {
  251.     sprintf(path,"%s/%s",full,dirent->d_name);
  252.  
  253.     if (stat ((char *) path, &statbuf) == -1) {
  254.       perror (path);
  255.       continue;
  256.     }
  257.     if(S_ISDIR(statbuf.st_mode)) {
  258.       if(self->dirNro >= EntryMax) continue;
  259.  
  260.       XtFree(self->dirTable[self->dirNro]);
  261.       self->dirTable[self->dirNro] = XtNewString(dirent->d_name);
  262.  
  263.       self->dirNro++;
  264.     } else {
  265.       if(self->fileNro >= EntryMax) continue;
  266.  
  267.       XtFree(self->fileTable[self->fileNro]);
  268.       self->fileTable[self->fileNro] = XtNewString(dirent->d_name);
  269.  
  270.       self->fileNro++;
  271.     }
  272.   }
  273.   closedir(dir);
  274.  
  275.   /*** free strings ***/
  276.   for(i = self->fileNro; i < fileOld; i++) {
  277.     XtFree(self->fileTable[i]);
  278.     self->fileTable[i] = NULL;
  279.   }
  280.   for(i = self->dirNro; i < dirOld; i++) {
  281.     XtFree(self->dirTable[i]);
  282.     self->dirTable[i] = NULL;
  283.   }
  284.  
  285.   /*** sort tables ***/
  286.   qsort(self->fileTable,self->fileNro,sizeof(String),(int (*)())StrCmp);
  287.   qsort(self->dirTable,self->dirNro,sizeof(String),(int (*)())StrCmp);
  288.  
  289.   /*** update ***/
  290.   XawListChange(self->fileList,self->fileTable,self->fileNro,0,True);
  291.   XawListChange(self->dirList,self->dirTable,self->dirNro,0,True);
  292. }
  293.  
  294. /**********************************************************************
  295.  * public
  296.  **********************************************************************/
  297.  
  298. /*
  299.  * create new instance of file-selector, no show
  300.  * dir is crossfire path eg "/"
  301.  * name: name of this module
  302.  * root: all 
  303.  * dir : starting directory
  304.  */
  305. CnvPath CnvPathCreate(String name,String root,String dir)
  306. {
  307.  
  308.  
  309.     CnvPath self;
  310.  
  311.     debug3("CnvPathCreate() %s %s %s\n",name,root,dir);
  312.     self  = (CnvPath) XtMalloc (sizeof (struct CnvPath));
  313.     memset(self,0,sizeof(struct CnvPath));
  314.     pathcpy(self->root,root);
  315.  
  316.     /*** initialize translations if not done ***/
  317.     if(hasActions == False) {
  318.     XtAppAddActions(XtWidgetToApplicationContext(cnv->shell),
  319.             actions,
  320.             XtNumber(actions));
  321.     hasActions = True;
  322.     }
  323.     Layout(self,name);
  324.     CnvPathListInit(self);
  325.     CnvCenterWidget(self->shell);
  326.     CnvPathListGet(self,dir);
  327.     return self;
  328. }
  329.  
  330. /*
  331.  * remove instance of file-selector
  332.  */
  333. void CnvPathDestroy(CnvPath self)
  334. {
  335.   int i;
  336.   debug("CnvPathDestroy()\n");
  337.  
  338.   for(i=0;i<self->dirNro;i++) XtFree(self->dirTable[i]);
  339.   for(i=0;i<self->fileNro;i++) XtFree(self->fileTable[i]);
  340.   XtDestroyWidget(self->shell);
  341. }
  342.  
  343. /*
  344.  * member: select a filepath
  345.  * return: PathResponce & results are in Path-structure 
  346.  */
  347. CnvPathResponce CnvPathSelect(CnvPath self)
  348. {
  349.   if(tmpCnvPath) {
  350.     CnvNotify("File Selector already in use",
  351.           "Continue",NULL);
  352.     return CnvPathCancel;
  353.   }
  354.   XtVaSetValues(self->text,
  355.         XtNstring,self->filename,
  356.         NULL);
  357.   /*** round ***/
  358.   tmpCnvPath = self;
  359.   self->hold = CnvPathHold;
  360.   XtPopup(self->shell,XtGrabExclusive);
  361.   while(self->hold == CnvPathHold) {
  362.     XtAppProcessEvent(XtWidgetToApplicationContext(self->shell),XtIMXEvent);
  363.   }
  364.   XtPopdown(self->shell);
  365.   tmpCnvPath = NULL;
  366.   return self->hold;
  367. }
  368.  
  369. /*
  370.  * member: select a filepath
  371.  * return: PathResponce & results are in Path-structure 
  372.  */
  373. CnvPathResponce CnvPathSelectAbs(CnvPath self,String path)
  374. {
  375.   if(tmpCnvPath) {
  376.     CnvNotify("File Selector already in use",
  377.           "Continue",NULL);
  378.     return CnvPathCancel;
  379.   }
  380.   XtVaSetValues(self->text,
  381.         XtNstring,self->filename,
  382.         NULL);
  383.   /*** round ***/
  384.   tmpCnvPath = self;
  385.   self->hold = CnvPathHold;
  386.   XtPopup(self->shell,XtGrabExclusive);
  387.   while(self->hold == CnvPathHold) {
  388.     XtAppProcessEvent(XtWidgetToApplicationContext(self->shell),XtIMXEvent);
  389.   }
  390.   XtPopdown(self->shell);
  391.   tmpCnvPath = NULL;
  392.   sprintf(path,"%s%s/%s",self->root,self->current,self->filename);
  393.   return self->hold;
  394. }
  395.  
  396. /**********************************************************************
  397.  * utility
  398.  **********************************************************************/
  399.  
  400. /*
  401.  * - path is full absolute name
  402.  * - return true if NO access
  403.  */
  404. Boolean CnvPathNoAccess(Widget w, String path)
  405. {
  406.   char buf[BUFSIZ];
  407.  
  408.   if (access (path, R_OK | X_OK) == -1) {
  409.     switch (errno) {
  410.     case EACCES:
  411.       sprintf (buf, "Permission denied for %s", path);
  412.       CnvNotify (buf,Continue,NULL);
  413.       break;
  414.     case ENOENT:
  415.       sprintf (buf, "%s does not exist", path);
  416.       CnvNotify (buf,Continue,NULL);
  417.       break;
  418.     case EIO:
  419.       sprintf (buf, "IO error in accessing %s", path);
  420.       CnvNotify (buf,Continue,NULL);
  421.       break;
  422.     case ENAMETOOLONG:
  423.     case ENOTDIR:
  424.       sprintf (buf, "Error in pathname for %s", path);
  425.       CnvNotify (buf,Continue);
  426.       break;
  427.     default:
  428.       sprintf (buf, "Error accessing to %s", path);
  429.       CnvNotify (buf,Continue,NULL);
  430.       break;
  431.     }
  432.     return True;
  433.   } else {
  434.     return False;
  435.   }
  436.  
  437. /* 
  438.  * - path is full absolute name
  439.  * - return true if NO access
  440.  */
  441. Boolean CnvPathNoWrite(Widget w, String path)
  442. {
  443.   char buf[BUFSIZ];
  444.  
  445.   if (access (path, R_OK | W_OK) == -1) {
  446.     switch (errno) {
  447.     case EACCES:
  448.       sprintf (buf, "Permission denied for %s", path);
  449.       CnvNotify (buf,Continue,NULL);
  450.       break;
  451.     case ENOENT:
  452.       sprintf (buf, "%s does noit exist", path);
  453.       CnvNotify (buf,Continue,NULL);
  454.       break;
  455.     case EIO:
  456.       sprintf (buf, "IO error in accessing %s", path);
  457.       CnvNotify (buf,Continue,NULL);
  458.       break;
  459.     case ENAMETOOLONG:
  460.     case ENOTDIR:
  461.       sprintf (buf, "Error in pathname for %s", path);
  462.       CnvNotify (buf,Continue);
  463.       break;
  464.     default:
  465.       sprintf (buf, "Error accessing to %s", path);
  466.       CnvNotify (buf,Continue,NULL);
  467.       break;
  468.     }
  469.     return True;
  470.   } else {
  471.     return False;
  472.   }
  473.  
  474. /*** end of CnvPath.c ***/
  475.  
  476.  
  477.